package mx.com.asteca.vista;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.model.SelectItem;

import mx.com.asteca.comun.Constantes;
import mx.com.asteca.comun.dto.AlumnoAsistenciaDTO;
import mx.com.asteca.comun.dto.AlumnoCalificacionMateriaDTO;
import mx.com.asteca.comun.dto.AlumnoDTO;
import mx.com.asteca.comun.dto.CatGralDTO;
import mx.com.asteca.comun.dto.CursoDTO;
import mx.com.asteca.comun.dto.MateriaDTO;
import mx.com.asteca.comun.dto.PermisosBooleanDTO;
import mx.com.asteca.fachada.CursoFachada;
import mx.com.asteca.fachada.FachadaException;
import mx.com.asteca.util.FechaUtil;

import org.springframework.util.CollectionUtils;

@ManagedBean(name = Constantes.BEAN_LISTA_ASISTENCIA)
@ViewScoped
public class ListaAsistenciaControlador extends BaseController {

	private final static String modulo = Constantes.MODULO_LISTA_ASISTENCIA;

	private PermisosBooleanDTO permisos;
	@ManagedProperty("#{cursoFachadaImpl}")
	private transient CursoFachada fachadaCurso;
	public String referencia;
	public boolean listaRendered;

	private List<SelectItem> listSelect;
	private List<AlumnoDTO> listaAlumnos;
	public Date minDate;
	public Date maxDate;
	private List<AlumnoAsistenciaDTO> listaAlumnosAsistencia;
	private List<String> encabezadoDias;
	private List<String> getEncabezadoMaterias;
	private List<AlumnoCalificacionMateriaDTO> listaAlumnosCalificaciones;
	private List<String> encabezadoMaterias;
	
	private String fechaInicioTeoria = "";
	private String fechaFinTeoria = "";
	CatGralDTO area = new CatGralDTO();
	CatGralDTO sede = new CatGralDTO();
	
	@PostConstruct
	public void populate() {
		setPermisos(super.stablishSessionPermissions());
	}

	/**
	 * @return the permisos
	 */
	public PermisosBooleanDTO getPermisos() {
		return permisos;
	}

	/**
	 * @param permisos
	 *            the permisos to set
	 */
	public void setPermisos(PermisosBooleanDTO permisos) {
		this.permisos = permisos;
		super.setAlta(permisos.isAlta());
		super.setBorrar(permisos.isBorrar());
		super.setCambios(permisos.isEdicion());
		super.setConsulta(permisos.isConsulta());
		super.setImpresion(permisos.isImpresion());
	}

	private void initListSelect(){
		if(CollectionUtils.isEmpty(listSelect)){
			listSelect = new ArrayList<SelectItem>();
			try {
				List<CursoDTO> lista = fachadaCurso.getAll();
				if(!CollectionUtils.isEmpty(lista)){
					for(CursoDTO dto : lista){
						SelectItem item = new SelectItem(dto.getReferencia(), dto.getReferencia());
						listSelect.add(item);
					}
				}
			} catch (FachadaException e) {
				super.addErrorMessage(Constantes.MESSAGE_TITLE_ERROR, Constantes.ERROR_OBTENIENDO_LISTA_CATALOGO);
			}
		}
	}
	
	
	public void despliegaLista(){
		if(referencia == null || referencia.isEmpty()){
			super.addWarningMessage(Constantes.MESSAGE_TITLE_WARNING, "Selecciona una referencia");
			return;
		}
		try {
			CursoDTO dto = fachadaCurso.findByReferencia(referencia);
			Date f_ini_teoria = dto.getFechaIni();
			Date f_fin_teoria = dto.getFechaFin();
			fechaInicioTeoria = FechaUtil.getInstance().parseDateMM_dd_yy(f_ini_teoria);
			fechaFinTeoria = FechaUtil.getInstance().parseDateMM_dd_yy(f_fin_teoria);
			int idArea = dto.getIdArea();
			int idSede = dto.getIdSede();
			
			List<CatGralDTO> listaAreas = fachadaCurso.findAreas();
			List<CatGralDTO> listSedes = fachadaCurso.findSedes();
			
			for(CatGralDTO dtoA : listaAreas){
				if(dtoA.getIdCatGral() == idArea){
					area = dtoA;
				}
			}
			
			for(CatGralDTO dtoB : listSedes){
				if(dtoB.getIdCatGral() == idSede){
					sede = dtoB;
				}
			}
			
			listaAlumnos = fachadaCurso.findAlumnosPorCurso(dto.getIdCurso());
			buildAlumnosMaterias(listaAlumnos, dto);
			buildAlumnosAsistencia(listaAlumnos, dto);
			listaRendered = true;
			if(CollectionUtils.isEmpty(listaAlumnos)){
				super.addWarningMessage(Constantes.MESSAGE_TITLE_WARNING, "No hay alumnos registrados para este curso");
			}
		} catch (FachadaException e) {
			super.addErrorMessage(Constantes.MESSAGE_TITLE_ERROR, Constantes.ERROR_OBTENIENDO_LISTA_CATALOGO);
		}
		
	}
	
	private void buildAlumnosAsistencia(List<AlumnoDTO> listaAlumnos,
			CursoDTO dtoCurso) {
		if(!CollectionUtils.isEmpty(listaAlumnos)){
			Date fechaInicio = dtoCurso.getFechaIni();
			Date fechaFin = dtoCurso.getFechaFin();
			minDate = fechaInicio;
			maxDate = fechaFin;
			Calendar calendarFin = Calendar.getInstance();
			calendarFin.setTime(fechaFin);
			Date fechaTemp = fechaInicio;
			List<String> dias = null;
			List<String> asistencias = null;
			Calendar cal = Calendar.getInstance();
			List<AlumnoAsistenciaDTO> listaAsistencia = new ArrayList<AlumnoAsistenciaDTO>();
			for (AlumnoDTO dto : listaAlumnos) {
				asistencias = new ArrayList<String>();
				dias = new ArrayList<String>();
				AlumnoAsistenciaDTO asistenciaDTO = new AlumnoAsistenciaDTO();
				asistenciaDTO.setMatricula(dto.getMatricula());
				asistenciaDTO.setNombre(dto.getNombre());
				fechaTemp = fechaInicio;
				while (fechaFin.after(fechaTemp) || (cal.get(Calendar.DAY_OF_YEAR) == calendarFin.get(Calendar.DAY_OF_YEAR))) {
					String asistencia;
					try {
						asistencia = fachadaCurso.findAsistencia(dto.getIdAlumno(), dtoCurso.getIdCurso(), fechaTemp);
					} catch (FachadaException e) {
						asistencia = "";
					}
					String dia = FechaUtil.getInstance().parseDateMM_dd_yy(
							fechaTemp);
					dias.add(dia);
					cal.setTime(fechaTemp);
					cal.add(Calendar.DATE, 1);
					fechaTemp = cal.getTime();
					//String asistencia = "S";
					asistencias.add(asistencia);
				}
				asistenciaDTO.setDias(dias);
				asistenciaDTO.setAsistencias(asistencias);
				listaAsistencia.add(asistenciaDTO);
			}
			setListaAlumnosAsistencia(listaAsistencia);			
			setEncabezadoDias(listaAsistencia.get(0).getDias());
		}
	}
	
	private void buildAlumnosMaterias(List<AlumnoDTO> listaAlumos, CursoDTO dtoCurso){
		try {
			List<MateriaDTO> listaMaterias = fachadaCurso.findMateriasPorCurso(dtoCurso.getIdCurso());
			if(!CollectionUtils.isEmpty(listaMaterias)){
				encabezadoMaterias = new ArrayList<String>();
				if(!CollectionUtils.isEmpty(listaMaterias)){
					for(MateriaDTO dto : listaMaterias){
						encabezadoMaterias.add(dto.getNombre());
					}
				}
				listaAlumnosCalificaciones = new ArrayList<AlumnoCalificacionMateriaDTO>();
				String calificacion = "";
				if(!CollectionUtils.isEmpty(listaAlumos)){
					for(AlumnoDTO dto2 : listaAlumos){
						List<String> listaCalificaciones = new ArrayList<String>();
						int idMateria = 0;
						if(!CollectionUtils.isEmpty(listaMaterias)){
							for(MateriaDTO dto : listaMaterias){
								calificacion = fachadaCurso.getCalificacion(dto2.getIdAlumno(), dtoCurso.getIdCurso(), dto.getIdMateria());
								listaCalificaciones.add(calificacion);
							}
						}
						AlumnoCalificacionMateriaDTO califAlumno = new AlumnoCalificacionMateriaDTO();
						califAlumno.setListaMaterias(encabezadoMaterias);
						califAlumno.setListCalificaciones(listaCalificaciones);
						califAlumno.setIdAlumno(dto2.getIdAlumno());
						califAlumno.setMatricula(dto2.getMatricula());
						califAlumno.setNombre(dto2.getNombre());
						listaAlumnosCalificaciones.add(califAlumno);
					}
				}
			}
		} catch (FachadaException e) {
			super.addErrorMessage(Constantes.MESSAGE_TITLE_ERROR, Constantes.ERROR_OBTENIENDO_LISTA_CATALOGO);
		}
	}
	
	@Override
	String getModulo() {
		return modulo;
	}

	/**
	 * @return the fachadaCurso
	 */
	public CursoFachada getFachadaCurso() {
		return fachadaCurso;
	}

	/**
	 * @param fachadaCurso the fachadaCurso to set
	 */
	public void setFachadaCurso(CursoFachada fachadaCurso) {
		this.fachadaCurso = fachadaCurso;
	}

	/**
	 * @return the listSelect
	 */
	public List<SelectItem> getListSelect() {
		initListSelect();
		return listSelect;
	}

	/**
	 * @param listSelect the listSelect to set
	 */
	public void setListSelect(List<SelectItem> listSelect) {
		this.listSelect = listSelect;
	}

	/**
	 * @return the referencia
	 */
	public String getReferencia() {
		return referencia;
	}

	/**
	 * @param referencia the referencia to set
	 */
	public void setReferencia(String referencia) {
		this.referencia = referencia;
	}

	/**
	 * @return the listaRendered
	 */
	public boolean isListaRendered() {
		return listaRendered;
	}

	/**
	 * @param listaRendered the listaRendered to set
	 */
	public void setListaRendered(boolean listaRendered) {
		this.listaRendered = listaRendered;
	}

	/**
	 * @return the listaAlumnos
	 */
	public List<AlumnoDTO> getListaAlumnos() {
		return listaAlumnos;
	}

	/**
	 * @param listaAlumnos the listaAlumnos to set
	 */
	public void setListaAlumnos(List<AlumnoDTO> listaAlumnos) {
		this.listaAlumnos = listaAlumnos;
	}

	/**
	 * @return the minDate
	 */
	public Date getMinDate() {
		return minDate;
	}

	/**
	 * @param minDate the minDate to set
	 */
	public void setMinDate(Date minDate) {
		this.minDate = minDate;
	}

	/**
	 * @return the maxDate
	 */
	public Date getMaxDate() {
		return maxDate;
	}

	/**
	 * @param maxDate the maxDate to set
	 */
	public void setMaxDate(Date maxDate) {
		this.maxDate = maxDate;
	}

	/**
	 * @return the listaAlumnosAsistencia
	 */
	public List<AlumnoAsistenciaDTO> getListaAlumnosAsistencia() {
		return listaAlumnosAsistencia;
	}

	/**
	 * @param listaAlumnosAsistencia the listaAlumnosAsistencia to set
	 */
	public void setListaAlumnosAsistencia(
			List<AlumnoAsistenciaDTO> listaAlumnosAsistencia) {
		this.listaAlumnosAsistencia = listaAlumnosAsistencia;
	}

	/**
	 * @return the encabezadoDias
	 */
	public List<String> getEncabezadoDias() {
		return encabezadoDias;
	}

	/**
	 * @param encabezadoDias the encabezadoDias to set
	 */
	public void setEncabezadoDias(List<String> encabezadoDias) {
		this.encabezadoDias = encabezadoDias;
	}

	/**
	 * @return the getEncabezadoMaterias
	 */
	public List<String> getGetEncabezadoMaterias() {
		return getEncabezadoMaterias;
	}

	/**
	 * @param getEncabezadoMaterias the getEncabezadoMaterias to set
	 */
	public void setGetEncabezadoMaterias(List<String> getEncabezadoMaterias) {
		this.getEncabezadoMaterias = getEncabezadoMaterias;
	}

	/**
	 * @return the listaAlumnosCalificaciones
	 */
	public List<AlumnoCalificacionMateriaDTO> getListaAlumnosCalificaciones() {
		return listaAlumnosCalificaciones;
	}

	/**
	 * @param listaAlumnosCalificaciones the listaAlumnosCalificaciones to set
	 */
	public void setListaAlumnosCalificaciones(
			List<AlumnoCalificacionMateriaDTO> listaAlumnosCalificaciones) {
		this.listaAlumnosCalificaciones = listaAlumnosCalificaciones;
	}

	/**
	 * @return the encabezadoMaterias
	 */
	public List<String> getEncabezadoMaterias() {
		return encabezadoMaterias;
	}

	/**
	 * @param encabezadoMaterias the encabezadoMaterias to set
	 */
	public void setEncabezadoMaterias(List<String> encabezadoMaterias) {
		this.encabezadoMaterias = encabezadoMaterias;
	}

	/**
	 * @return the fechaInicioTeoria
	 */
	public String getFechaInicioTeoria() {
		return fechaInicioTeoria;
	}

	/**
	 * @param fechaInicioTeoria the fechaInicioTeoria to set
	 */
	public void setFechaInicioTeoria(String fechaInicioTeoria) {
		this.fechaInicioTeoria = fechaInicioTeoria;
	}

	/**
	 * @return the fechaFinTeoria
	 */
	public String getFechaFinTeoria() {
		return fechaFinTeoria;
	}

	/**
	 * @param fechaFinTeoria the fechaFinTeoria to set
	 */
	public void setFechaFinTeoria(String fechaFinTeoria) {
		this.fechaFinTeoria = fechaFinTeoria;
	}

	/**
	 * @return the area
	 */
	public CatGralDTO getArea() {
		return area;
	}

	/**
	 * @param area the area to set
	 */
	public void setArea(CatGralDTO area) {
		this.area = area;
	}

	/**
	 * @return the sede
	 */
	public CatGralDTO getSede() {
		return sede;
	}

	/**
	 * @param sede the sede to set
	 */
	public void setSede(CatGralDTO sede) {
		this.sede = sede;
	}

}
